import { _decorator, Component, Node, Vec2, Vec3 } from 'cc';
import { EventConst, Singleton } from '../../common/Common';
import { SpriteFrame } from 'cc';
import UtilTool from '../../tools/UtilTool';
import { PlayBaseUser } from './PlayBaseUser';
import { App } from '../../App';
import { Prefab } from 'cc';
import { showErrorTip, showTip } from '../../tools/PopuUp';
import { PD } from '../../player/PlayerData';

import { GameModel3 } from './mode3/GameModel3';
import { MultiCommon } from '../../hall/multiplay/MultiCommon';
import GameConst from '../../const/GameConst';
import { GameModel4 } from './mode4/GameModel4';
import AbstractComponent from '../../base/AbstractComponent';
import { GameBaseModel } from './GameBaseModel';
import { resources } from 'cc';
import { JsonAsset } from 'cc';
import { error } from 'cc';
import { LoadMg } from '../../tools/LoadMg';
import CommConst from '../../const/CommConst';
import { GameModel5 } from './mode5/GameModel5';
const { ccclass, property } = _decorator;


/** 游戏常量 */
export const BALL_RADIUS = 4.8; // 球的半径 // 175
export const MAX_FORCE = 100 //400 // 最大力度
export const MAX_FORCE_BOMB = 300 // 最大爆炸力度（开球的时候用的最大力度）
export const WHITE_BALL = 0 // 白球0(母球)
export const BLACK_BALL = 8 // 黑球8
export const ACTION_POINT_R = 406 // 作用点球的半径
export const FOUR_BALL_BASE = 16 // 四轮球的基础球号
export const GAME_HITBALL_TIME = 30 // 游戏击球时间
export const BLOOD_PLAYDRAGON_ANIM = 16 // 血流模式播放飞龙动画分数（基础分）


export const CLIENTMSG_SWITCH = false // 使用本地消息开关

export const SYSTEM_ADDRESS = "system_address" // 默认系统玩家地址

export const GAME_RES_LIST = [
    {path: "images/ball2D_2", type: SpriteFrame, isDir : true},
    {path: "images/ball2D", type: SpriteFrame, isDir : true},
    {path: "images/combo", type: SpriteFrame, isDir : true},
    {path: "images/gameCue", type: SpriteFrame, isDir : true},
    {path: "prefabs/game/comboNode", type: Prefab, isDir : false},

    // {path: "prefab/game/ball", type: Prefab},
    // {path: "prefab/game/ball", type: Prefab},
]

/** 多人游戏类型 */
export enum GAME_MULTI_TYPE {
    NONE = 0,           // 无
    PT_MULIT = 1,       // 普通房多人
    PT_FOURBALL = 2,    // 普通房4球开伦
    ZY_MULIT = 3,       // 专业房多人
    ZY_FOURBALL = 4,    // 专业房4球开伦
}

/* 游戏公共管理类 */
export class GameManage extends AbstractComponent {
    public BALL_DIA_2D = 50 // 球的2D直径

    // 存放其它15个球的数组
    public otherBallArr = []  

    // 存放其它15个球的UI数组
    public otherBallArrUI = []

    // 游戏开始数据(多人+四球开伦)
    gameStartData = null

    // 游戏开始数据(血流)
    gameStartBloodData = null

    // 断线重连数据
    gameReconnectData = null

    // 断线重连服务器数据
    serverReconnectData = null

    // 多人游戏观战数据
    gameWatchData = null
    
    // 房主地址
    houseOwnerAccount = ""

    // 房间号
    roomId = ""

    // 房间类型
    roomType = 0 // [0]普通房 [1]专业房

    // 多人游戏类型
    gameType = GAME_MULTI_TYPE.NONE

    // 多人游戏是否是观战
    isWatchGame = false

    // 服务器下发数据 (房间信息发生变化)
    roomInfoChange = null

    // 所有玩家正在使用的球杆信息
    playerUsingClubInfo = null

    // 负责上报帧数据的玩家(主要是用于多人模式系统出杆的时候)
    uploadAccount = ""

    // 击球作用点坐标位置
    ballActionPoint = new Vec2(0, 0)

    // 击球作用点弧刻度
    ballActionDial = 0

    // 击球作用点坐标位置
    ballActionPoint_other = new Vec2(0, 0)

    // 击球作用点弧刻度
    ballActionDial_other = 0

    // 帧数据
    frameData: object = []

    static instance: any = null
    public static getInstance(): GameManage {
        if (this.instance == null) {
            this.instance = new GameManage();
        }
        return this.instance;
    }

    constructor() {
        super()
        this.init()
    }

    init() {
        if (CLIENTMSG_SWITCH){
            this.gameStartData = {
                "msgCode":510,
                "roomId":"001",
                "gameType":0,
                "roomType":0,
                "dynamics":0,
                "angle":0,
                "houseOwnerAccount":"",
                "targetBall":{"myAdddress":[],"testAddress":[]},
                "allBallInfo":[],
                "firstHitBallPlayerFinger":"",
                "currentHitPlayer":"",
                "cueBall":[],
                "nicknameMap":{},
                "playerUsingClubInfo":{},
                "headIdMap":{},
            }

            this.gameStartBloodData = {
                "msgCode":524,
                "roomId":"001",
                "gameType":0,
                "roomType":0,
                "bloodLevel":0,
                "nicknameMap":{},
                "playerUsingClubInfo":{},
                "playerGold":{},
                "currentHitPlayer":"",
                "firstHitBallPlayerFinger":"",
                "allBallInfo":[],
                "headIdMap":{},
            }

            // resources.load('frameData', (err: any, res: JsonAsset) => {
            //     if (err) {
            //         error(err.message || err);
            //         return;
            //     }
            //     // 获取到 Json 数据
            //     this.frameData = res.json;
            //     UtilTool.printLog("frameData=>>>>>>>>",this.frameData)
            // })
        }
        
    }

    /** 
     * 接受服务器消息
    */
    respGameMsg(data) {
        
        let msgCode = data.msgCode
        switch(msgCode) {
            case GameConst.Resp_GAME_START: // (多人对战)游戏开始
                UtilTool.printLog("multigame 游戏开始", data)
                // this.gameReconnectData = null // 正常走游戏开始的话，需要把断线重连的数据清除
                // this.gameWatchData = null
                // this.isWatchGame = false

                this.resqGameStart(data)
                break;

            case GameConst.Resp_FOURGAME_START: // (四球开伦)游戏开始
                UtilTool.printLog("fourgame 游戏开始", data)
                this.resqGameStart(data)
                break;

            case GameConst.Resp_BLOODGAME_START: // (血流模式)游戏开始
                UtilTool.printLog("bloodgame 游戏开始", data)
                this.resqGameStartBlood(data)
                break;

            case GameConst.Resp_RECONNECT_MULTIGAME: // 重连成功后下发的消息(多人对战)
                UtilTool.printLog("multigame 多人模式重连成功后下发的消息", data)

                if (App.Scene.curScene == "game3" || 
                    App.Scene.curScene == "game4" ||
                    App.Scene.curScene == "multiroom"
                ){
                    this.resqGameMultiReconnect(data)
                }
                else{
                    this.serverReconnectData = data
                }
                
                break;

            case GameConst.Resp_RECONNECT_FOUR: // 重连成功后下发的消息(四球开伦)
                UtilTool.printLog("fourgame 四球开伦模式重连成功后下发的消息", data)

                if (App.Scene.curScene == "game3" || 
                    App.Scene.curScene == "game4" ||
                    App.Scene.curScene == "multiroom"
                ){
                    this.resqGameMultiReconnect(data)
                }
                else{
                    this.serverReconnectData = data
                }
                break;

            case GameConst.Resp_RECONNECT_BLOOD: // 重连成功后下发的消息(血流模式)
                UtilTool.printLog("fourgame 血流模式重连成功后下发的消息", data)

                if (App.Scene.curScene == "game5"){
                    this.resqGameBloodReconnect(data)
                }
                else{
                    this.serverReconnectData = data
                }
                break;

            case GameConst.Req_WATCH_GAME: // 响应观战
                UtilTool.printLog("multigame 响应观战", data)
                this.resqGameMultiWatch(data)
                break;

            case CommConst.Resq_BLOOD_MATCH_SUCCEED: // （血流模式）匹配成功
                UtilTool.printLog("bloodgame 匹配成功（血流模式）", data)
                App.Event.emit(EventConst.BLOOD_MATCH_CUC, data)
                break;


                

            default:
                {
                    break;
                }
        }
    }

    /** 
     * 服务器通知游戏开始 [进入游戏]
    */
    resqGameStart(data) {
        if (data==null) {
            showTip(App.language.getLanguageLab(136))
            return
        }
        this.gameStartData = data
        this.houseOwnerAccount = data.houseOwnerAccount
        this.roomId = data.roomId
        this.roomType = data.roomType
        this.uploadAccount = data.uploadAccount || ""
        this.setGameType(data.roomType, data.gameType)
        this.setPlayerCue(data.playerUsingClubInfo)

        // 游戏类型 0多人对战 1四球开伦
        if (data.gameType == 0){
            App.Scene.go("game3")
        }
        else if (data.gameType == 1){
            App.Scene.go("game4")
        }
        
    }

    /** 
     * 服务器通知游戏开始 [血流模式]
    */
    resqGameStartBlood(data) {
        if (data==null) {
            showTip(App.language.getLanguageLab(136))
            return
        }
        this.gameStartBloodData = data
        this.roomId = data.roomId
        this.roomType = data.roomType
        this.uploadAccount = data.uploadAccount || ""
        this.setPlayerCue(data.playerUsingClubInfo)

        App.Scene.go("game5")
    }

    /** 
     *  多人场断线重连(多人 + 四球开伦)
    */
    resqGameMultiReconnect(data) {
        let gameView = null
        if (data.gameType == 0) { // 多人
            gameView = App.Model.gameView as GameModel3
        }
        else if (data.gameType == 1){ // 四球
            gameView = App.Model.gameView as GameModel4
        }
        
        if (data==null) {
            showTip(App.language.getLanguageLab(136))
            setTimeout(() => {
                this.backToMultiRoom()
            }, 3000);
            return
        }

        if (data.result!=0) {
            // 1019玩家不在房间内
            showErrorTip(data.result)
            setTimeout(() => {
                this.backToMultiRoom()
            }, 3000);
            
            return
        }

        App.fightMode = App.fightMode_3

        // 当前房间状态 0等待中 1开球中 2游戏中
        if (data.currentRoomStatus==0) { 
            UtilTool.printLog("断线重连 房间中")

            data.waitStatusInfo["houseOwnerAccount"] = data.houseOwnerAccount
            data.waitStatusInfo["gameType"] = data.gameType
            data.waitStatusInfo["roomId"] = data.roomId
            data.waitStatusInfo["roomType"] = data.roomType
            data.waitStatusInfo["nicknameMap"] = data.nicknameMap

            let fromGameData = {
                joinData : data.waitStatusInfo,
                exitType : 1
            }
            setTimeout(() => {
                this.backToMultiRoom(this.roomType, fromGameData)
            }, 500);
            
        }
        else {
            this.gameReconnectData = data

            if (data.gameType == 0) { // 多人
                data.playingStatusInfo["roomId"] = data.roomId
                data.playingStatusInfo["currentRoomStatus"] = data.currentRoomStatus
            }
            else if (data.gameType == 1){ // 四球
                data.fourBallInfo["roomId"] = data.roomId
                data.fourBallInfo["currentRoomStatus"] = data.currentRoomStatus
            }

            this.setGameStartData(data)
 
            if (gameView){ // 已经在游戏场景
                this.houseOwnerAccount = data.houseOwnerAccount
                this.roomId = data.roomId
                this.roomType = data.roomType
                this.setGameType(data.roomType, data.gameType)
                this.setPlayerCue(this.gameStartData.playerUsingClubInfo)

                if (data.gameType == 0) { // 多人
                    gameView.gameLogic.respGameReconnect(data.playingStatusInfo)
                }
                else if (data.gameType == 1){ // 四球
                    gameView.gameLogic.respGameReconnect(data.fourBallInfo)
                }
            }
            else{ // 还没有在游戏场景
                // setTimeout(() => {
                    this.resqGameStart(this.gameStartData)
                // }, 1000);
            }

            if (data.currentRoomStatus==1) {
                UtilTool.printLog("断线重连 开球中")
            }
            else if (data.currentRoomStatus==2) {
                UtilTool.printLog("断线重连 游戏中")
            }
        }
    }

    /** 
     *  血流到底断线重连
    */
    resqGameBloodReconnect(data) {
        let gameView = App.Model.gameView as GameModel5
        
        if (data==null) {
            showTip(App.language.getLanguageLab(136))
            setTimeout(() => {
                this.backToBloodSelect()
            }, 3000);
            return
        }

        if (data.result!=0) {
            // 1019玩家不在房间内
            showErrorTip(data.result)
            setTimeout(() => {
                this.backToBloodSelect()
            }, 3000);
            
            return
        }

        App.fightMode = App.fightMode_4

        // 当前房间状态 0等待中 1猜拳中 2游戏中
        if (data.currentRoomStatus==0) { 
        }
        else {
            this.gameReconnectData = data
            this.setGameStartData(data)
 
            if (gameView){ // 已经在游戏场景
                this.roomId = data.roomId
                this.roomType = data.roomType
                this.setPlayerCue(this.gameStartBloodData.playerUsingClubInfo)

                gameView.gameLogic.respGameReconnect(data)
            }
            else{ // 还没有在游戏场景
                // setTimeout(() => {
                    this.resqGameStartBlood(this.gameStartBloodData)
                // }, 1000);
            }

            if (data.currentRoomStatus==1) {
                UtilTool.printLog("断线重连 猜拳中")
            }
            else if (data.currentRoomStatus==2) {
                UtilTool.printLog("断线重连 游戏中")
            }
        }
    }

    /**
     * 检测断线重连
     */
    checkReCount = 6
    checkReconnect() {
        let that = this
        this.checkReCount = 6

        let func = function() {
            if (that.serverReconnectData) {
                if (that.serverReconnectData.gameType==0 || that.serverReconnectData.gameType==1){
                    that.resqGameMultiReconnect(that.serverReconnectData)
                }
                else if (that.serverReconnectData.gameType==2) {
                    that.resqGameBloodReconnect(that.serverReconnectData)
                }
            }
            else{
                if (that.checkReCount<=0) return
                that.checkReCount = that.checkReCount - 1

                setTimeout(() => {
                    func()
                }, 500);
            }
        }

        func()
    }

    /** 
     *  多人场观战(多人+四球开伦)
    */
    resqGameMultiWatch(data) {
        if (data==null) {
            showTip(App.language.getLanguageLab(136))
            return
        }

        if (data.result!=0) {
            // 0正常 1006房间类型错误 1010房间不存在 1011进入房间密码错误 1023房间不允许观战 1021玩家已在房间内 1016台球游戏状态异常
            showErrorTip(data.result)
            return
        }
        
        App.fightMode = App.fightMode_3

        // 当前房间状态 0等待中 1开球中 2游戏中
        if (data.currentRoomStatus==0) { 
            UtilTool.printLog("多人场观战 房间中")
        }
        else {
            this.gameWatchData = data
            if (data.gameType == 0) { // 多人
                data.playingStatusInfo["roomId"] = data.roomId
                data.playingStatusInfo["currentRoomStatus"] = data.currentRoomStatus
            }
            else if (data.gameType == 1){ // 四球
                data.fourBallInfo["roomId"] = data.roomId
                data.fourBallInfo["currentRoomStatus"] = data.currentRoomStatus
            }
            
            this.setGameStartData(data)
            this.isWatchGame = true

            // 还没有在游戏场景
            this.resqGameStart(this.gameStartData)

            if (data.currentRoomStatus==1) {
                UtilTool.printLog("观战 开球中")
            }
            else if (data.currentRoomStatus==2) {
                UtilTool.printLog("观战 游戏中")
            }
        }
    }

    // 断线重连回来的观战处理(直接退出观战场景)
    reconnectWatch() {
        if (this.isWatchGame) {
            let gameView = App.Model.gameView as GameBaseModel
            if (gameView) {
                showTip(App.language.getLanguageLab(145))
                setTimeout(() => {
                    gameView && gameView.backToMultiRoom()
                }, 3000);
            }
        }
    }

    // 退出观战
    quitWatch() {
        if (this.isWatchGame) {
            let gameView = App.Model.gameView as GameBaseModel
            if (gameView) {
                LoadMg.showLoad({type:1})
                showTip(App.language.getLanguageLab(146))
                setTimeout(() => {
                    LoadMg.removeLoad()
                    gameView && gameView.backToMultiRoom()
                }, 3000);
            }
        }
    }

    // 退出多人游戏场景
    quitGameScene() {
        let gameView = App.Model.gameView as GameBaseModel
        if (gameView) {
            setTimeout(() => {
                gameView && gameView.backToMultiRoom()
            }, 3000);
        }
    }


    // 设置游戏开始数据(多人+四球开伦)
    setGameStartData(data) {
        if (data == null) {
            return
        }

        if (data.gameType == 0) { // 多人
           if (data.playingStatusInfo==null) return

           let gameStartData = {
                "msgCode":510,
                "roomId":data.roomId,
                "gameType":data.gameType,
                "roomType":data.roomType,
                "dynamics":data.playingStatusInfo.dynamics || 15,
                "angle":data.playingStatusInfo.angle || 0,
                "houseOwnerAccount":data.houseOwnerAccount,
                "targetBall":data.playingStatusInfo.targetBall,
                "playerUsingClubInfo":data.playingStatusInfo.playerUsingClubInfo,
                "nicknameMap":data.nicknameMap,
                "headIdMap":data.headIdMap,
            } 

            this.gameStartData = gameStartData
        }
        else if (data.gameType == 1){ // 四球
            if (data.fourBallInfo==null) return

            let gameStartData = {
                "msgCode":519,
                "roomId":data.roomId,
                "gameType":data.gameType,
                "roomType":data.roomType,
                "allBallInfo":data.fourBallInfo.allBallInfo,
                "firstHitBallPlayerFinger":data.fourBallInfo.firstHitBallPlayerFinger,
                "houseOwnerAccount":data.houseOwnerAccount,
                "currentHitPlayer":data.fourBallInfo.currentHitPlayer,
                "cueBall":data.fourBallInfo.cueBall,
                "playerUsingClubInfo":data.fourBallInfo.playerUsingClubInfo,
                "nicknameMap":data.nicknameMap,
                "headIdMap":data.headIdMap,
            } 
    
            this.gameStartData = gameStartData
        }
        else if (data.gameType == 2){ // 血流到底
            let gameStartBloodData = {
                "msgCode":524,
                "roomId":data.roomId,
                "gameType":data.gameType,
                "roomType":data.roomType,
                "bloodLevel":data.bloodLevel,
                "nicknameMap":data.nicknameMap,
                "playerUsingClubInfo":data.playerUsingClubInfo,
                "playerGold":data.playerGold,
                "currentHitPlayer":data.currentHitPlayer,
                "firstHitBallPlayerFinger":data.firstHitBallPlayerFinger,
                "allBallInfo":data.allBallInfo,
                "headIdMap":data.headIdMap,
            }
    
            this.gameStartBloodData = gameStartBloodData
        }

    }

    // 自己是否是房主
    getIsOwner() {
        return PD.user.addressUrl == this.houseOwnerAccount
    }

    // 是否是断线重连，而且是在游戏中的状态
    isReconnectAndGameing() {
        return this.gameReconnectData
    }

    // 设置多人游戏类型
    setGameType(roomType, gameType) {
        this.gameType = GAME_MULTI_TYPE.NONE
        if (roomType==0) { // 普通房
            if (gameType==0) {
                this.gameType = GAME_MULTI_TYPE.PT_MULIT
            }else if (gameType==1) {
                this.gameType = GAME_MULTI_TYPE.PT_FOURBALL
            }
        }else if (roomType==1) { // 专业房
            if (gameType==0) {
                this.gameType = GAME_MULTI_TYPE.ZY_MULIT
            }else if (gameType==1) {
                this.gameType = GAME_MULTI_TYPE.ZY_FOURBALL
            }
        }
    }

    /** 
     * 设置所有玩家的球杆信息
    */
    setPlayerCue(data) {
        this.playerUsingClubInfo = data
    }

    /** 
     * 获取对应玩家的球杆编号
    */
    getPlayerCueNumber(address) {
        if (this.playerUsingClubInfo==null) {
            return PD.user.defaultCue
        }

        let cueInfo = this.playerUsingClubInfo[address]
        if (cueInfo == null) {
            return PD.user.defaultCue
        }

        return cueInfo.number
    }

    /** 
     * 获取对应玩家的球杆信息
    */
    getPlayerCueInfo(address) {
        if (this.playerUsingClubInfo==null) {
            return PD.defaultCueInfo
        }

        let cueInfo = this.playerUsingClubInfo[address]
        if (cueInfo == null) {
            cueInfo= PD.defaultCueInfo
        }

        return cueInfo
    }


    /** 
     * 设置击球作用点位置
    */
    setActionPoint(pos) {
        this.ballActionPoint.x = pos.x
        this.ballActionPoint.y = pos.y
    }

    /** 
     * 设置击球作用点位置(其它玩家的)
    */
    setActionPoint_other(ballActionP) { 
        this.ballActionPoint_other.x = ballActionP[0]
        this.ballActionPoint_other.y = ballActionP[1]
    }

    /** 
     * 设置击球作用点弧刻度(其它玩家的)
    */
    setBallActionDial_other(ballActionDial) { 
        this.ballActionDial_other = ballActionDial
    }

    /** 
     * 获取击球作用点弧刻度
    */
    getBallActionDial() { 
        let gameView = App.Model.gameView as GameBaseModel
        if (gameView.cueCtrl.isMine){
            return this.ballActionDial
        }
        else{
            return this.ballActionDial_other
        }
    }

    /** 
     * 设置击球作用点在冲量里面的作用点位置
     * @param angle 击球角度
    */
    getActionPointImpulse(ballAngle) {
        let ballActionPoint = null
        let gameView = App.Model.gameView as GameBaseModel
        if (gameView.cueCtrl.isMine){
            ballActionPoint = this.ballActionPoint
        }
        else{
            ballActionPoint = this.ballActionPoint_other
        }

        let ratio = BALL_RADIUS / ACTION_POINT_R
        let posY = ratio * ballActionPoint.y

        let posX = 0
        let posZ = 0
        let startP = new Vec2(0, 0)
        let lenX = Math.abs(ratio * ballActionPoint.x)
        

        let angle = UtilTool.getRAngle(ballAngle - 90)
        let p = UtilTool.getPointMove3(startP, angle, lenX)
        if (ballAngle>=0 && ballAngle<=90) {
            if (ballActionPoint.x<0) {
                posX = Math.abs(p.y)
                posZ = -Math.abs(p.x)
            }
            else{
                posX = -Math.abs(p.y)
                posZ = Math.abs(p.x)
            }
        }
        else if (ballAngle>90 && ballAngle<=180) {
            if (ballActionPoint.x<0) {
                posX = Math.abs(p.y)
                posZ = Math.abs(p.x)
            }
            else{
                posX = -Math.abs(p.y)
                posZ = -Math.abs(p.x)
            }
        }
        else if (ballAngle>180 && ballAngle<=270) {
            if (ballActionPoint.x<0) {
                posX = -Math.abs(p.y)
                posZ = Math.abs(p.x)
            }
            else{
                posX = Math.abs(p.y)
                posZ = -Math.abs(p.x)
            }

        }
        else if (ballAngle>270 && ballAngle<=360) {
            if (ballActionPoint.x<0) {
                posX = -Math.abs(p.y)
                posZ = -Math.abs(p.x)
            }
            else{
                posX = Math.abs(p.y)
                posZ = Math.abs(p.x)
            }
        }

        return new Vec3(posX, posY, posZ)
    }

    /** 
     * 清理数据
    */
    public clear() {
        this.otherBallArr = []
        this.otherBallArrUI = []
        this.gameStartData = null
        this.houseOwnerAccount = ""
        this.roomId = ""
        this.gameType = GAME_MULTI_TYPE.NONE
        this.roomInfoChange = null
        this.gameReconnectData = null
        this.serverReconnectData = null
        
        this.gameWatchData = null
        this.isWatchGame = false
        this.ballActionPoint.x = 0 
        this.ballActionPoint.y = 0 
        this.ballActionDial = 0

        this.ballActionPoint_other.x = 0 
        this.ballActionPoint_other.y = 0 
        this.ballActionDial_other = 0

        this.playerUsingClubInfo = null
        this.uploadAccount = ""

        this.gameStartBloodData = null
    }

}
